package com.dy.yunying.biz.service.datacenter.impl;

import com.dy.yunying.api.datacenter.vo.RealTimeKanbanSummaryVO;
import com.dy.yunying.api.datacenter.vo.RealTimeKanbanTimeSharing;
import com.dy.yunying.api.datacenter.vo.RealTimeKanbanTimeSharingVO;
import com.dy.yunying.api.entity.RealTimeKanbanDO;
import com.dy.yunying.api.entity.RealTimeKanbanRatio;
import com.dy.yunying.api.enums.RealTimeKanbanEnums;
import com.dy.yunying.api.enums.RealTimeKanbanTrendEnum;
import com.dy.yunying.biz.dao.datacenter.impl.RealTimeKanbanDao;
import com.dy.yunying.biz.service.datacenter.RealTimeKanbanService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author sunyq
 * @date 2022/8/17 9:28
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RealTimeKanbanServiceImpl implements RealTimeKanbanService {

	private final RealTimeKanbanDao realTimeKanbanDao;

	private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

	private String[] timeArray = new String[]{"01:00","02:00","03:00","04:00","05:00","06:00","07:00","08:00","09:00","10:00","11:00","12:00",
			"13:00","14:00","15:00","16:00","17:00","18:00","19:00","20:00","21:00","22:00","23:00","24:00"};

	private String[] index = new String []{"accountNums","deviceNums","activePayAmounts","activeFeeAccounts","activeAccounts","payFeeRate"};


	private Map<String,String> timeMap = new HashMap<>();

	private Map<String,String> titleMap = new HashMap<>();

	@PostConstruct
	public void initTimeMap(){
		timeMap.put("0","01:00");
		timeMap.put("1","02:00");
		timeMap.put("2","03:00");
		timeMap.put("3","04:00");
		timeMap.put("4","05:00");
		timeMap.put("5","06:00");
		timeMap.put("6","07:00");
		timeMap.put("7","08:00");
		timeMap.put("8","09:00");
		timeMap.put("9","10:00");
		timeMap.put("10","11:00");
		timeMap.put("11","12:00");
		timeMap.put("12","13:00");
		timeMap.put("13","14:00");
		timeMap.put("14","15:00");
		timeMap.put("15","16:00");
		timeMap.put("16","17:00");
		timeMap.put("17","18:00");
		timeMap.put("18","19:00");
		timeMap.put("19","20:00");
		timeMap.put("20","21:00");
		timeMap.put("21","22:00");
		timeMap.put("22","23:00");
		timeMap.put("23","24:00");


		titleMap.put("accountNums","新增账户");
		titleMap.put("deviceNums","新增设备");
		titleMap.put("activePayAmounts","充值金额");
		titleMap.put("activeFeeAccounts","充值人数");
		titleMap.put("activeAccounts","活跃账户");
		titleMap.put("payFeeRate","付费率");
	}



	@Override
	public List<RealTimeKanbanSummaryVO> summary() {
		LocalDate today = LocalDate.now();
		LocalDate yesterday = today.plusDays(-1);
		LocalDate lastWeek = today.plusWeeks(-1);
		RealTimeKanbanDO todayRealTimeKanbanDO = realTimeKanbanDao.summary(today.format(formatter));
		RealTimeKanbanDO yesterdayRealTimeKanbanDO = realTimeKanbanDao.summary(yesterday.format(formatter));
		RealTimeKanbanDO lastWeekRealTimeKanbanDO = realTimeKanbanDao.summary(lastWeek.format(formatter));
		List<RealTimeKanbanSummaryVO> result = new ArrayList<>();
		//
		//Field[] fields = todayRealTimeKanbanDO.getClass().getDeclaredFields();

		//新增账户
		BigDecimal accountNums = todayRealTimeKanbanDO.getAccountNums();
		BigDecimal yesAccountNums = yesterdayRealTimeKanbanDO.getAccountNums();
		BigDecimal lastWeekAccountNums = lastWeekRealTimeKanbanDO.getAccountNums();
		RealTimeKanbanSummaryVO accountNumsVO = new RealTimeKanbanSummaryVO();
		accountNumsVO.setData(accountNums.stripTrailingZeros().toPlainString());
		accountNumsVO.setColor(RealTimeKanbanEnums.ACCOUNT_NUM.getColor());
		accountNumsVO.setName(RealTimeKanbanEnums.ACCOUNT_NUM.getName());
		accountNumsVO.setTips(RealTimeKanbanEnums.ACCOUNT_NUM.getTips());
		setFromRatio(accountNumsVO, accountNums, yesAccountNums, lastWeekAccountNums);
		result.add(accountNumsVO);
		//新增设备
		BigDecimal deviceNums = todayRealTimeKanbanDO.getDeviceNums();
		BigDecimal yesDeviceNums = yesterdayRealTimeKanbanDO.getDeviceNums();
		BigDecimal lastWeekDeviceNums = lastWeekRealTimeKanbanDO.getDeviceNums();
		RealTimeKanbanSummaryVO deviceNumsVO = new RealTimeKanbanSummaryVO();
		deviceNumsVO.setData(deviceNums.stripTrailingZeros().toPlainString());
		deviceNumsVO.setColor(RealTimeKanbanEnums.DIVICE_NUM.getColor());
		deviceNumsVO.setName(RealTimeKanbanEnums.DIVICE_NUM.getName());
		deviceNumsVO.setTips(RealTimeKanbanEnums.DIVICE_NUM.getTips());
		setFromRatio(deviceNumsVO, deviceNums, yesDeviceNums, lastWeekDeviceNums);
		result.add(deviceNumsVO);

		//充值金额
		BigDecimal activePayAmounts = todayRealTimeKanbanDO.getActivePayAmounts();
		BigDecimal yesActivePayAmounts = yesterdayRealTimeKanbanDO.getActivePayAmounts();
		BigDecimal lastWeekActivePayAmounts = lastWeekRealTimeKanbanDO.getActivePayAmounts();
		RealTimeKanbanSummaryVO activePayAmountsVO = new RealTimeKanbanSummaryVO();
		activePayAmountsVO.setData(activePayAmounts.stripTrailingZeros().toPlainString());
		activePayAmountsVO.setColor(RealTimeKanbanEnums.ACTIVE_PAY_AMOUNTS.getColor());
		activePayAmountsVO.setName(RealTimeKanbanEnums.ACTIVE_PAY_AMOUNTS.getName());
		activePayAmountsVO.setTips(RealTimeKanbanEnums.ACTIVE_PAY_AMOUNTS.getTips());
		setFromRatio(activePayAmountsVO, activePayAmounts, yesActivePayAmounts, lastWeekActivePayAmounts);
		result.add(activePayAmountsVO);

		//充值人数
		BigDecimal activeFeeAccounts = todayRealTimeKanbanDO.getActiveFeeAccounts();
		BigDecimal yesActiveFeeAccounts = yesterdayRealTimeKanbanDO.getActiveFeeAccounts();
		BigDecimal lastWeekActiveFeeAccounts = lastWeekRealTimeKanbanDO.getActiveFeeAccounts();
		RealTimeKanbanSummaryVO activeFeeAccountsVO = new RealTimeKanbanSummaryVO();
		activeFeeAccountsVO.setData(activeFeeAccounts.stripTrailingZeros().toPlainString());
		activeFeeAccountsVO.setColor(RealTimeKanbanEnums.ACTIVE_FEE_ACCOUNTS.getColor());
		activeFeeAccountsVO.setName(RealTimeKanbanEnums.ACTIVE_FEE_ACCOUNTS.getName());
		activeFeeAccountsVO.setTips(RealTimeKanbanEnums.ACTIVE_FEE_ACCOUNTS.getTips());
		setFromRatio(activeFeeAccountsVO, activeFeeAccounts, yesActiveFeeAccounts, lastWeekActiveFeeAccounts);
		result.add(activeFeeAccountsVO);
		//活跃账号
		BigDecimal activeAccounts = todayRealTimeKanbanDO.getActiveAccounts();
		BigDecimal yesActiveAccounts = yesterdayRealTimeKanbanDO.getActiveAccounts();
		BigDecimal lastWeekActiveAccounts = lastWeekRealTimeKanbanDO.getActiveAccounts();
		RealTimeKanbanSummaryVO activeAccountsVO = new RealTimeKanbanSummaryVO();
		activeAccountsVO.setData(activeAccounts.stripTrailingZeros().toPlainString());
		activeAccountsVO.setColor(RealTimeKanbanEnums.ACTIVE_ACCOUNTS.getColor());
		activeAccountsVO.setName(RealTimeKanbanEnums.ACTIVE_ACCOUNTS.getName());
		activeAccountsVO.setTips(RealTimeKanbanEnums.ACTIVE_ACCOUNTS.getTips());
		setFromRatio(activeAccountsVO, activeAccounts, yesActiveAccounts, lastWeekActiveAccounts);
		result.add(activeAccountsVO);

		BigDecimal payFeeRate = todayRealTimeKanbanDO.getPayFeeRate();
		BigDecimal yesPayFeeRate = yesterdayRealTimeKanbanDO.getPayFeeRate();
		BigDecimal lastWeekPayFeeRate = lastWeekRealTimeKanbanDO.getPayFeeRate();
		RealTimeKanbanSummaryVO payFeeRateVO = new RealTimeKanbanSummaryVO();
		payFeeRateVO.setData(payFeeRate.stripTrailingZeros().toPlainString()+"%");
		payFeeRateVO.setColor(RealTimeKanbanEnums.PAY_FEE_RATE.getColor());
		payFeeRateVO.setName(RealTimeKanbanEnums.PAY_FEE_RATE.getName());
		payFeeRateVO.setTips(RealTimeKanbanEnums.PAY_FEE_RATE.getTips());
		setFromRatio(payFeeRateVO, payFeeRate, yesPayFeeRate, lastWeekPayFeeRate);
		result.add(payFeeRateVO);

		return result;
	}

	@Override
	public List<RealTimeKanbanTimeSharingVO> timeSharing() {
		LocalDate today = LocalDate.now();
		LocalDate yesterday = today.plusDays(-1);
		LocalDate lastWeek = today.plusWeeks(-1);
		List<RealTimeKanbanDO> todayRealTimeKanbanDO = realTimeKanbanDao.timeSharing(today.format(formatter));
		List<RealTimeKanbanDO> yesterdayRealTimeKanbanDO = realTimeKanbanDao.timeSharing(yesterday.format(formatter));
		List<RealTimeKanbanDO> lastWeekRealTimeKanbanDO = realTimeKanbanDao.timeSharing(lastWeek.format(formatter));
		List<RealTimeKanbanTimeSharingVO> result = new ArrayList<>();
		initResult(result);

		for (RealTimeKanbanDO realTimeKanbanDO : todayRealTimeKanbanDO) {
			String dataTime = realTimeKanbanDO.getDataTime();
			BigDecimal accountNums = realTimeKanbanDO.getAccountNums();
			BigDecimal deviceNums = realTimeKanbanDO.getDeviceNums();
			BigDecimal activePayAmounts = realTimeKanbanDO.getActivePayAmounts();
			BigDecimal activeAccounts = realTimeKanbanDO.getActiveAccounts();
			BigDecimal activeFeeAccounts = realTimeKanbanDO.getActiveFeeAccounts();
			BigDecimal payFeeRate = realTimeKanbanDO.getPayFeeRate();
			setTodayRealTimeKanban(result, dataTime, accountNums,"accountNums");
			setTodayRealTimeKanban(result, dataTime, deviceNums,"deviceNums");
			setTodayRealTimeKanban(result, dataTime, activePayAmounts,"activePayAmounts");
			setTodayRealTimeKanban(result, dataTime, activeAccounts,"activeAccounts");
			setTodayRealTimeKanban(result, dataTime, activeFeeAccounts,"activeFeeAccounts");
			setTodayRealTimeKanban(result, dataTime, payFeeRate,"payFeeRate");

		}

		for (RealTimeKanbanDO realTimeKanbanDO : yesterdayRealTimeKanbanDO) {
			String dataTime = realTimeKanbanDO.getDataTime();
			BigDecimal accountNums = realTimeKanbanDO.getAccountNums();
			BigDecimal deviceNums = realTimeKanbanDO.getDeviceNums();
			BigDecimal activePayAmounts = realTimeKanbanDO.getActivePayAmounts();
			BigDecimal activeAccounts = realTimeKanbanDO.getActiveAccounts();
			BigDecimal activeFeeAccounts = realTimeKanbanDO.getActiveFeeAccounts();
			BigDecimal payFeeRate = realTimeKanbanDO.getPayFeeRate();
			setYesRealTimeKanban(result, dataTime, accountNums,"accountNums");
			setYesRealTimeKanban(result, dataTime, deviceNums,"deviceNums");
			setYesRealTimeKanban(result, dataTime, activePayAmounts,"activePayAmounts");
			setYesRealTimeKanban(result, dataTime, activeAccounts,"activeAccounts");
			setYesRealTimeKanban(result, dataTime, activeFeeAccounts,"activeFeeAccounts");
			setYesRealTimeKanban(result, dataTime, payFeeRate,"payFeeRate");


		}

		for (RealTimeKanbanDO realTimeKanbanDO : lastWeekRealTimeKanbanDO) {
			String dataTime = realTimeKanbanDO.getDataTime();
			BigDecimal accountNums = realTimeKanbanDO.getAccountNums();
			BigDecimal deviceNums = realTimeKanbanDO.getDeviceNums();
			BigDecimal activePayAmounts = realTimeKanbanDO.getActivePayAmounts();
			BigDecimal activeAccounts = realTimeKanbanDO.getActiveAccounts();
			BigDecimal activeFeeAccounts = realTimeKanbanDO.getActiveFeeAccounts();
			BigDecimal payFeeRate = realTimeKanbanDO.getPayFeeRate();
			setLastWeekRealTimeKanban(result, dataTime, accountNums,"accountNums");
			setLastWeekRealTimeKanban(result, dataTime, deviceNums,"deviceNums");
			setLastWeekRealTimeKanban(result, dataTime, activePayAmounts,"activePayAmounts");
			setLastWeekRealTimeKanban(result, dataTime, activeAccounts,"activeAccounts");
			setLastWeekRealTimeKanban(result, dataTime, activeFeeAccounts,"activeFeeAccounts");
			setLastWeekRealTimeKanban(result, dataTime, payFeeRate,"payFeeRate");
		}
		return result;
	}

	private void setLastWeekRealTimeKanban(List<RealTimeKanbanTimeSharingVO> result, String dataTime, BigDecimal accountNums, String key) {
		for (RealTimeKanbanTimeSharingVO realTimeKanbanTimeSharingVO : result) {
			if (realTimeKanbanTimeSharingVO.getName().equals(key)) {
				List<RealTimeKanbanTimeSharing> data = realTimeKanbanTimeSharingVO.getData();
				for (RealTimeKanbanTimeSharing kanbanTimeSharing : data) {
					if (kanbanTimeSharing.getTime().equals(timeMap.get(dataTime))) {
						kanbanTimeSharing.setLastWeekToday(accountNums.stripTrailingZeros().toPlainString());
					}
				}
				break;
			}
		}
//		List<RealTimeKanbanTimeSharingVO> accountNumsList = result.get(key);
//		for (RealTimeKanbanTimeSharingVO realTimeKanbanTimeSharingVO : accountNumsList) {
//			if (realTimeKanbanTimeSharingVO.getTime().equals(timeMap.get(dataTime))){
//				realTimeKanbanTimeSharingVO.setLastWeekToday(accountNums.stripTrailingZeros().toPlainString());
//			}
//		}
	}

	private void setYesRealTimeKanban(List<RealTimeKanbanTimeSharingVO> result, String dataTime, BigDecimal accountNums, String key) {

		for (RealTimeKanbanTimeSharingVO realTimeKanbanTimeSharingVO : result) {
			if (realTimeKanbanTimeSharingVO.getName().equals(key)) {
				List<RealTimeKanbanTimeSharing> data = realTimeKanbanTimeSharingVO.getData();
				for (RealTimeKanbanTimeSharing kanbanTimeSharing : data) {
					if (kanbanTimeSharing.getTime().equals(timeMap.get(dataTime))) {
						kanbanTimeSharing.setYesterday(accountNums.stripTrailingZeros().toPlainString());
					}
				}
				break;
			}
		}
//		List<RealTimeKanbanTimeSharingVO> accountNumsList = result.get(key);
//		for (RealTimeKanbanTimeSharingVO realTimeKanbanTimeSharingVO : accountNumsList) {
//			if (realTimeKanbanTimeSharingVO.getTime().equals(timeMap.get(dataTime))){
//				realTimeKanbanTimeSharingVO.setYesterday(accountNums.stripTrailingZeros().toPlainString());
//			}
//		}
	}

	private void setTodayRealTimeKanban(List<RealTimeKanbanTimeSharingVO> result, String dataTime, BigDecimal accountNums,String key) {
		for (RealTimeKanbanTimeSharingVO realTimeKanbanTimeSharingVO : result) {
			if (realTimeKanbanTimeSharingVO.getName().equals(key)) {
				List<RealTimeKanbanTimeSharing> data = realTimeKanbanTimeSharingVO.getData();
				for (RealTimeKanbanTimeSharing kanbanTimeSharing : data) {
					if (kanbanTimeSharing.getTime().equals(timeMap.get(dataTime))) {
						kanbanTimeSharing.setToday(accountNums.stripTrailingZeros().toPlainString());
					}
				}
				break;
			}
		}
//		List<RealTimeKanbanTimeSharingVO> accountNumsList = result.get(key);
//		for (RealTimeKanbanTimeSharingVO realTimeKanbanTimeSharingVO : accountNumsList) {
//			if (realTimeKanbanTimeSharingVO.getTime().equals(timeMap.get(dataTime))){
//				realTimeKanbanTimeSharingVO.setToday(accountNums.stripTrailingZeros().toPlainString());
//			}
//		}
	}

	private void initResult(List<RealTimeKanbanTimeSharingVO> result) {
		LocalDateTime now = LocalDateTime.now();
		int hour = now.getHour();
		for (int i = 0; i < index.length; i++) {
			RealTimeKanbanTimeSharingVO realTimeKanbanTimeSharingVO = new RealTimeKanbanTimeSharingVO();
			realTimeKanbanTimeSharingVO.setName(index[i]);
			realTimeKanbanTimeSharingVO.setTitle(titleMap.get(index[i]));
			List<RealTimeKanbanTimeSharing> list = new ArrayList<>();
			for (int j = 0; j < timeArray.length; j++) {
				RealTimeKanbanTimeSharing realTimeKanbanTimeSharing = new RealTimeKanbanTimeSharing();
				realTimeKanbanTimeSharing.setTime(timeArray[j]);
				if (j<=hour){
					realTimeKanbanTimeSharing.setToday("0");
				} else {
					realTimeKanbanTimeSharing.setToday("-");
				}
				realTimeKanbanTimeSharing.setYesterday("0");
				realTimeKanbanTimeSharing.setLastWeekToday("0");
				list.add(realTimeKanbanTimeSharing);
			}
			realTimeKanbanTimeSharingVO.setData(list);
			result.add(realTimeKanbanTimeSharingVO);
		}

	}

	private void setFromRatio(RealTimeKanbanSummaryVO realTimeKanbanSummaryVO, BigDecimal accountNums, BigDecimal yesAccountNums, BigDecimal lastWeekAccountNums) {
		RealTimeKanbanRatio dayFromRatio = getFromRatio(accountNums, yesAccountNums);
		RealTimeKanbanRatio weekFromRatio = getFromRatio(accountNums, lastWeekAccountNums);
		realTimeKanbanSummaryVO.setDaysFromRatio(dayFromRatio);
		realTimeKanbanSummaryVO.setWeeksFromRatio(weekFromRatio);
	}

	private RealTimeKanbanRatio getFromRatio(BigDecimal accountNums, BigDecimal yesAccountNums) {
		RealTimeKanbanRatio fromRatio = new RealTimeKanbanRatio();
		if (yesAccountNums.compareTo(BigDecimal.ZERO)!=0){
			BigDecimal bigDecimal = accountNums.subtract(yesAccountNums).multiply(BigDecimal.TEN).multiply(BigDecimal.TEN)
					.divide(yesAccountNums,2,RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP);
			if (bigDecimal.compareTo(BigDecimal.ZERO) > 0){
				fromRatio.setTrend(RealTimeKanbanTrendEnum.UP.getTrend());
			} else if (bigDecimal.compareTo(BigDecimal.ZERO) < 0){
				fromRatio.setTrend(RealTimeKanbanTrendEnum.DOWN.getTrend());
			} else{
				fromRatio.setTrend(RealTimeKanbanTrendEnum.FLAT.getTrend());
			}
			fromRatio.setRatio(bigDecimal.abs().toPlainString()+"%");
		} else {
			fromRatio.setRatio("0.00 %");
			fromRatio.setTrend(RealTimeKanbanTrendEnum.FLAT.getTrend());
		}
		return fromRatio;
	}
}
